package com.ruoyi.system.monitor;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.enums.LevelEnum;
import com.ruoyi.system.domain.MonitorConfig;
import com.ruoyi.system.domain.vo.MonitorDatabaseCountVo;
import com.ruoyi.system.domain.vo.WarnDigestDTO;
import com.ruoyi.system.domain.vo.WarnDigestDetailVo;
import com.ruoyi.system.service.impl.SysConfigServiceImpl;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.SimpleDriverDataSource;
import org.springframework.stereotype.Component;

import javax.sql.DataSource;
import java.util.Date;
import java.util.List;

@Component
public class MfoService implements MonitorDataService {

    @Autowired
    private SysConfigServiceImpl sysConfigService;

    @Override
    public WarnDigestDTO count(MonitorConfig config) {
        String interval = sysConfigService.selectConfigByKey("mfo.interval");
        JdbcTemplate jdbcTemplate = getJdbcTemplate(config);
        String sql = String.format("SELECT\n" +
                " LVL AS severity,\n" +
                " COUNT(1) AS count,\n" +
                " MAX(TIME) AS lastestTime\n" +
                "FROM ora_alarm_history \n" +
                "WHERE TIME >= SYSDATE - INTERVAL %s \n" +
                "GROUP BY LVL\n" +
                "UNION ALL\n" +
                "SELECT \n" +
                " LVL AS severity,\n" +
                " COUNT(1) AS count,\n" +
                " MAX(TIME) AS lastestTime\n" +
                "FROM ORA_ALERTLOG_HISTORY\n" +
                "WHERE TIME >= SYSDATE - INTERVAL %s\n" +
                "GROUP BY LVL\n", interval, interval);
        List<MonitorDatabaseCountVo> query = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(MonitorDatabaseCountVo.class));
        WarnDigestDTO vo = merge(query, config);
        if (vo.hasCount()) {
            vo.setDetailList(getDetailVoList(null, jdbcTemplate));
        }
        return vo;
    }

    @Override
    public List<WarnDigestDetailVo> detail(MonitorConfig config, LevelEnum type) {
        JdbcTemplate jdbcTemplate = getJdbcTemplate(config);
        return getDetailVoList(type, jdbcTemplate);
    }

    @NotNull
    private List<WarnDigestDetailVo> getDetailVoList(LevelEnum type, JdbcTemplate jdbcTemplate) {
        String interval = sysConfigService.selectConfigByKey("mfo.interval");
        String condition = getCondition(type);
        String sql = String.format("SELECT\n" +
                "  instance,\n" +
                "  time,\n" +
                "  name,\n" +
                "  value,\n" +
                "  lvl AS \"level\",\n" +
                "  log\n" +
                "FROM (\n" +
                "  SELECT\n" +
                "    b.INSTANCE_NAME AS instance,\n" +
                "    a.TIME AS time,\n" +
                "    a.NAME AS name,\n" +
                "    a.VALUE AS VALUE,\n" +
                "    a.lvl,\n" +
                "    a.DESCRIPTION AS log\n" +
                "  FROM ora_alarm_history a\n" +
                "  LEFT JOIN apm_db_info b ON a.DB_ID = b.DB_ID\n" +
                "  WHERE TIME >= SYSDATE - INTERVAL %s\n" +
                "  %s \n" +
                "  UNION ALL\n" +
                "  SELECT \n" +
                "    b.INSTANCE_NAME,\n" +
                "    a.TIME,\n" +
                "    NULL AS NAME,\n" +
                "    NULL AS VALUE,\n" +
                "    a.lvl,\n" +
                "    a.VALUE\n" +
                "  FROM ORA_ALERTLOG_HISTORY a\n" +
                "  LEFT JOIN apm_db_info b ON a.DB_ID = b.DB_ID\n" +
                "  WHERE TIME >= SYSDATE - INTERVAL %s\n" +
                "  %s \n" +
                ") T\n" +
                "ORDER BY TIME DESC", interval, condition, interval , condition);
        return jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(WarnDigestDetailVo.class));
    }

    @Override
    public DataSource getDataSource(MonitorConfig config) {
        SimpleDriverDataSource driverDataSource = new SimpleDriverDataSource();
        String paramStr = config.getParams();
        JSONObject params = JSON.parseObject(paramStr);

        driverDataSource.setDriverClass(oracle.jdbc.driver.OracleDriver.class);
        String dbUrl = "jdbc:oracle:thin:@//%s:%s/%s";
        dbUrl = String.format(dbUrl, params.getString("url"), params.getString("port"), params.getString("dbName"));
        driverDataSource.setUrl(dbUrl);
        //设置用户名和密码
        driverDataSource.setUsername(params.getString("username"));
        driverDataSource.setPassword(params.getString("password"));

        return driverDataSource;
    }

    private String getCondition(LevelEnum type) {
        if (type == null) {
            return "";
        }
        String where = "AND LVL = ";
        if (type == LevelEnum.NORMAL) {
            return where + "0";
        } else if (type == LevelEnum.WARNING) {
            return where + "1";
        }
        return where + "2";
    }


    private static WarnDigestDTO merge(List<MonitorDatabaseCountVo> voList, MonitorConfig config) {
        int normal = 0;
        int warning = 0;
        int critical = 0;
        for (MonitorDatabaseCountVo vo : voList) {
            if (vo.getSeverity() == 0) {
                normal += vo.getCount();
            } else if (vo.getSeverity() == 1) {
                warning += vo.getCount();
            } else if (vo.getSeverity() == 2) {
                critical += vo.getCount();
            }
        }
        Date latestTime = voList.stream().map(MonitorDatabaseCountVo::getLastestTime).max(Date::compareTo).orElse(null);
        JSONObject serverParams = JSON.parseObject(config.getHostParams());
        return new WarnDigestDTO()
                .setConfigId(config.getId())
                .setConfigType(config.getType())
                .setName(config.getName())
                .setSort(config.getSort())
                .setNormal(normal)
                .setWarning(warning)
                .setCritical(critical)
                .setLastestTime(latestTime)
                .setHref(serverParams.getString("url"));
    }
}
